// $codepro.audit.disable numericLiterals
package com.googlecode.cchlib.apps.regexbuilder;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.HyperlinkEvent;
import com.googlecode.cchlib.awt.DesktopHelper;
import com.googlecode.cchlib.awt.PlatformDesktopNotSupportedException;

/**
 *
 *
 */
public class RegExpBuilderFrame
    extends JFrame
        implements HyperlinkListener
{
    private static final long serialVersionUID = 1L;
    private XRegExpBuilderPanel panel;

    /**
     *  Construct the frame
     */
    public RegExpBuilderFrame()
    {
        enableEvents( AWTEvent.WINDOW_EVENT_MASK );

        try {
            setIconImage(Toolkit.getDefaultToolkit().getImage(RegExpBuilderPanel.class.getResource("icon.gif")));
            //setIconImage(Toolkit.getDefaultToolkit().getImage(RegExpBuilderWB.class.getResource("com/googlecode/cchlib/apps/regexbuilder/icon.gif")));
            }
        catch( Exception e ) {
            e.printStackTrace();
            }

        try {
            initComponents();
            }
        catch( Exception e ) {
            e.printStackTrace();
            }
    }

    private void initComponents()
    {
        BorderLayout    borderLayout1         = new BorderLayout();
        JPanel contentPane = (JPanel)this.getContentPane();
        contentPane.setLayout( borderLayout1 );
        this.setFont( new java.awt.Font( "Dialog", 0, 12 ) );
        this.setSize( new Dimension(720, 520) );
        this.setTitle( "Regular Expressions Tester" );

        contentPane.setPreferredSize( new Dimension( 438, 142 ) );

        panel = new XRegExpBuilderPanel();
        getContentPane().add(panel, BorderLayout.CENTER);
    }

    /*
    // Component initialization
    private void jbInit() throws Exception
    {
        contentPane = (JPanel)this.getContentPane();
        contentPane.setLayout( borderLayout1 );
        this.setFont( new java.awt.Font( "Dialog", 0, 12 ) );
        this.setSize( new Dimension( 629, 523 ) );
        this.setTitle( "Regular Expressions Tester" );
        jPanel1.setAlignmentY( (float)0.5 );
        jPanel1.setLayout( borderLayout2 );
        jSplitPane1.setOrientation( JSplitPane.VERTICAL_SPLIT );
        jSplitPane1.setBottomComponent( jSplitPane2 );
        jSplitPane1.setLeftComponent( jPanel1 );
        jSplitPane1.setRightComponent( null );
        jPanel2.setLayout( borderLayout3 );
        jLabel1.setAlignmentX( (float)0.0 );
        jLabel1.setMinimumSize( new Dimension( 97, 15 ) );
        jLabel1.setLabelFor( textRegex );
        jLabel1.setText( "Regular Expression:" );
        jEditorPane_Info.addHyperlinkListener( this );
        jEditorPane_Info.setEditable(false);
        jEditorPane_Info.setContentType("text/html");
        jEditorPane_Info.setText( "<html>Visit <a href=\"http://www.regular-expressions.info\">http://www.regular-expressions.info</a> for a complete regex tutorial</html>" );
        textRegex.setFont( new java.awt.Font( "Monospaced", 0, 12 ) );
        textRegex.setBorder( BorderFactory.createLoweredBevelBorder() );
        textRegex.setText( "t[a-z]+" );
        textRegex.setLineWrap( true );
        jPanel3.setLayout( gridLayout1 );
        gridLayout1.setColumns( 2 );
        gridLayout1.setHgap( 2 );
        gridLayout1.setRows( 2 );
        gridLayout1.setVgap( 2 );
        checkDotAll.setText( "Dot matches newlines" );
        checkCanonEquivalence
                .setText( "Ignore differences in Unicode encoding" );
        checkMultiLine.setText( "^ and $ match at embedded newlines" );
        checkCaseInsensitive.setText( "Case insensitive" );
        contentPane.setPreferredSize( new Dimension( 438, 142 ) );
        jPanel4.setLayout( borderLayout4 );
        jPanel6.setAlignmentX( (float)0.5 );
        jPanel6.setLayout( borderLayout5 );
        jPanel5.setLayout( gridLayout2 );
        gridLayout2.setColumns( 5 );
        gridLayout2.setHgap( 2 );
        gridLayout2.setRows( 2 );
        gridLayout2.setVgap( 2 );
        btnMatch.setText( "Match Test" );
        btnMatch.addActionListener( new FrameRegexDemo_btnMatch_actionAdapter(
                this ) );
        btnSplit.setText( "Split" );
        btnSplit.addActionListener( new FrameRegexDemo_btnSplit_actionAdapter(
                this ) );
        btnObjects.setAlignmentY( (float)0.5 );
        btnObjects.setActionCommand( "Create Objects" );
        btnObjects.setText( "Create Objects" );
        btnObjects
                .addActionListener( new FrameRegexDemo_btnObjects_actionAdapter(
                        this ) );
        btnNextMatch.setText( "Next Match" );
        btnNextMatch
                .addActionListener( new FrameRegexDemo_btnNextMatch_actionAdapter(
                        this ) );
        btnObjReplace.setSelected( false );
        btnObjReplace.setText( "Obj Replace" );
        btnObjReplace
                .addActionListener( new FrameRegexDemo_btnObjReplace_actionAdapter(
                        this ) );
        btnObjSplit.setText( "Obj Split" );
        btnObjSplit
                .addActionListener( new FrameRegexDemo_btnObjSplit_actionAdapter(
                        this ) );
        btnReplace.setText( "Replace" );
        btnReplace
                .addActionListener( new FrameRegexDemo_btnReplace_actionAdapter(
                        this ) );
        jLabel3.setPreferredSize( new Dimension( 0, 0 ) );
        jLabel3.setRequestFocusEnabled( true );
        jLabel3.setText( "" );
        jLabel4.setLabelFor( textSubject );
        jLabel4.setText( "Test Subject:" );
        textSubject.setBorder( BorderFactory.createLoweredBevelBorder() );
        textSubject.setToolTipText( "" );
        textSubject
                .setText( "This is the default test subject for our regex test." );
        textSubject.setLineWrap( true );
        textSubject.setWrapStyleWord( true );
        jPanel8.setLayout( gridLayout3 );
        gridLayout3.setColumns( 2 );
        gridLayout3.setHgap( 4 );
        jPanel7.setLayout( borderLayout6 );
        jLabel5.setMaximumSize( new Dimension( 89, 15 ) );
        jLabel5.setLabelFor( textReplace );
        jLabel5.setText( "Replacement Text:" );
        textReplace.setBorder( BorderFactory.createLoweredBevelBorder() );
        textReplace.setToolTipText( "" );
        textReplace.setText( "replacement" );
        textReplace.setLineWrap( true );
        textReplace.setWrapStyleWord( true );
        borderLayout4.setVgap( 4 );
        borderLayout2.setVgap( 4 );
        borderLayout1.setHgap( 0 );
        borderLayout1.setVgap( 0 );
        jPanel9.setLayout( gridLayout4 );
        gridLayout4.setColumns( 2 );
        gridLayout4.setHgap( 4 );
        jSplitPane2.setOrientation( JSplitPane.VERTICAL_SPLIT );
        jPanel10.setLayout( borderLayout7 );
        jPanel11.setLayout( borderLayout8 );
        jLabel6.setToolTipText( "" );
        jLabel6.setLabelFor( textResults );
        jLabel6.setText( "Results:" );
        textResults.setBorder( BorderFactory.createLoweredBevelBorder() );
        textResults.setText( "" );
        textResults.setLineWrap( true );
        textResults.setWrapStyleWord( true );
        jLabel7.setLabelFor( textReplaceResults );
        jLabel7.setText( "Replacement Results:" );
        textReplaceResults.setBorder( BorderFactory.createLoweredBevelBorder() );
        textReplaceResults.setText( "" );
        textReplaceResults.setLineWrap( true );
        textReplaceResults.setWrapStyleWord( true );
        jLabel8.setRequestFocusEnabled( true );
        jLabel8.setText( "" );
        btnAdvancedReplace.setText( "Advanced Replace" );
        btnAdvancedReplace
                .addActionListener( new FrameRegexDemo_btnAdvancedReplace_actionAdapter(
                        this ) );
        contentPane.add( jSplitPane1, BorderLayout.CENTER );
        jSplitPane1.add( jSplitPane2, JSplitPane.RIGHT );
        jSplitPane1.add( jPanel1, JSplitPane.LEFT );
        jPanel1.add( jPanel2, BorderLayout.NORTH );
        jPanel2.add( jLabel1, BorderLayout.CENTER );
        jPanel2.add( jEditorPane_Info, BorderLayout.EAST );
        jPanel1.add( textRegex, BorderLayout.CENTER );
        jPanel1.add( jPanel3, BorderLayout.SOUTH );
        jPanel3.add( checkDotAll, null );
        jPanel3.add( checkCaseInsensitive, null );
        jPanel3.add( checkMultiLine, null );
        jPanel3.add( checkCanonEquivalence, null );
        jSplitPane2.add( jPanel4, JSplitPane.LEFT );
        jPanel4.add( jPanel5, BorderLayout.SOUTH );
        jPanel5.add( btnMatch, null );
        jPanel5.add( jLabel3, null );
        jPanel5.add( jLabel8, null );
        jPanel5.add( btnReplace, null );
        jPanel5.add( btnSplit, null );
        jPanel5.add( btnObjects, null );
        jPanel5.add( btnNextMatch, null );
        jPanel5.add( btnObjReplace, null );
        jPanel5.add( btnAdvancedReplace, null );
        jPanel5.add( btnObjSplit, null );
        jPanel6.add( jLabel4, BorderLayout.NORTH );
        jPanel6.add( textSubject, BorderLayout.CENTER );
        jPanel4.add( jPanel8, BorderLayout.CENTER );
        jPanel8.add( jPanel6, null );
        jSplitPane1.setDividerLocation( 150 );
        jSplitPane2.setDividerLocation( 200 );
        jPanel8.add( jPanel7, null );
        jPanel7.add( jLabel5, BorderLayout.NORTH );
        jPanel7.add( textReplace, BorderLayout.CENTER );
        jSplitPane2.add( jPanel9, JSplitPane.RIGHT );
        jPanel9.add( jPanel10, null );
        jPanel10.add( jLabel6, BorderLayout.NORTH );
        jPanel10.add( textResults, BorderLayout.CENTER );
        jPanel9.add( jPanel11, null );
        jPanel11.add( jLabel7, BorderLayout.NORTH );
        jPanel11.add( textReplaceResults, BorderLayout.CENTER );
    }
*/
    // Overridden so we can exit when window is closed
    @Override
    protected void processWindowEvent( WindowEvent e )
    {
        super.processWindowEvent( e );
        if( e.getID() == WindowEvent.WINDOW_CLOSING ) {
            System.exit( 0 );
        }
    }


    private static class XRegExpBuilderPanel extends RegExpBuilderPanel
    {
        private static final long serialVersionUID = 1L;

    /**
     * The easiest way to check if a particular string matches a regular
     * expression is to simply call String.matches() passing the regular
     * expression to it. It is not possible to set matching options this way, so
     * the checkboxes in this demo are ignored when clicking btnMatch.
     * <p>
     *
     * One disadvantage of this method is that it will only return true if the
     * regex matches the *entire* string. In other words, an implicit caret is
     * prepended to the regex and an implicit dollar sign is appended to it. So
     * you cannot use matches() to test if a substring anywhere in the string
     * matches the regex.
     * <p>
     *
     * Note that when typing in a regular expression into textSubject,
     * backslashes are interpreted at the regex level. So typing in \( will
     * match a literal ( character and \\ matches a literal backslash. When
     * passing literal strings in your source code, you need to escape
     * backslashes in strings as usual. So the string "\\(" matches a literal (
     * and "\\\\" matches a single literal backslash.
     */
    @Override
    public void btnMatch_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
        final JTextArea textSubject         = getTextSubject();
        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();

        textReplaceResults.setText( "n/a" );
        // Calling the Pattern.matches static method is an alternative way to
        // achieve the same
        // if (Pattern.matches(textRegex.getText(), textSubject.getText())) {
        try {
            if( textSubject.getText().matches( textRegex.getText() ) ) {
                textResults.setText( "The regex matches the entire subject" );
            } else {
                textResults.setText( "The regex does not match the entire subject" );
            }
        }
        catch( PatternSyntaxException ex ) {
            textResults.setText(
                    "You have an error in your regular expression:\n"
                            + ex.getDescription()
                            );
        }
    }

    /**
     * The easiest way to perform a regular expression search-and-replace on a
     * string is to call the string's replaceFirst() and replaceAll() methods.
     * replaceAll() will replace all substrings that match the regular
     * expression with the replacement string, while replaceFirst() will only
     * replace the first match.
     * <p>
     *
     * Again, you cannot set matching options this way, so the checkboxes in
     * this demo are ignored when clicking btnMatch.
     * <p>
     *
     * In the replacement text, you can use $0 to insert the entire regex match,
     * and $1, $2, $3, etc. for the backreferences (text matched by the part in
     * the regex between the first, second, third, etc. pair of round brackets)<br>
     * \$ inserts a single $ character.
     * <p>
     *
     * $$ or other improper use of the $ sign will raise an
     * IllegalArgumentException. If you reference a group that does not exist
     * (e.g. $4 if there are only 3 groups), will raise an
     * IndexOutOfBoundsException. Be sure to properly handle these exceptions if
     * you allow the end user to type in the replacement text.
     * <p>
     *
     * Note that in the memo control, you type \$ to insert a dollar sign, and
     * \\ to insert a backslash. If you provide the replacement string as a
     * string literal in your Java code, you need to use "\\$" and "\\\\"
     * respectively. This is because backslashes need to be escaped in Java
     * string literals as well.
     */
    @Override
    public void btnReplace_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
        final JTextArea textSubject         = getTextSubject();
        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
        final JTextArea textReplace         = getTextReplace();

        try {
            textReplaceResults.setText(
                    textSubject.getText().replaceAll(
                            textRegex.getText(),
                            textReplace.getText()
                            )
                        );
            textResults.setText( "n/a" );
        }
        catch( PatternSyntaxException ex ) {
            // textRegex does not contain a valid regular expression
            textResults.setText(
                    "You have an error in your regular expression:\n"
                            + ex.getDescription()
                            );
            textReplaceResults.setText( "n/a" );
        }
        catch( IllegalArgumentException ex ) {
            // textReplace contains inapropriate dollar signs
            textResults.setText(
                    "You have an error in the replacement text:\n"
                    + ex.getMessage()
                    );
            textReplaceResults.setText( "n/a" );
        }
        catch( IndexOutOfBoundsException ex ) {
            // textReplace contains a backreference that does not exist
            // (e.g. $4 if there are only three groups)
            textResults.setText(
                    "You have used a non-existent group in the replacement text:\n"
                            + ex.getMessage()
                            );
            textReplaceResults.setText( "n/a" );
        }
    }

    /** Show the results of splitting a string. */
    void printSplitArray( final String[] array )
    {
        final JTextArea textResults = getTextResults();

        textResults.setText( null );

        for( int i = 0; i < array.length; i++ ) {
            textResults.append(
                    Integer.toString( i )
                    + ": \""
                    + array[ i ]
                    + "\"\r\n"
                    );
        }
    }

    /**
     * The easiest way to split a string into an array of strings is by calling
     * the string's split() method. The string will be split at each substring
     * that matches the regular expression. The regex matches themselves are
     * thrown away.
     * <p>
     *
     * If the split would result in trailing empty strings, i.e. when the regex
     * matches at the end of the string, the trailing empty strings are also
     * thrown away. If you want to keep the empty strings, call split(regex,
     * -1). The -1 tells the split() method to add trailing empty strings to the
     * resulting array.
     * <p>
     *
     * You can limit the number of items in the resulting array by specifying a
     * positive number as the second parameter to split(). The limit you specify
     * it the number of items the array will at most contain. So the regex is
     * applied at most limit-1 times, and the last item in the array contains
     * the unsplit remainder of the original string. If you are only interested
     * in the first 3 items in the array, specify a limit of 4 and disregard the
     * last item. This is more efficient than having the string split
     * completely.
     */
    @Override
    public void btnSplit_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
        final JTextArea textSubject         = getTextSubject();
        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
//        final JTextArea textReplace         = getTextReplace();

        textReplaceResults.setText( "n/a" );
        try {
            printSplitArray(
                    textSubject.getText().split(
                            textRegex.getText() /* , Limit */
                            )
                        );
        }
        catch( PatternSyntaxException ex ) {
            // textRegex does not contain a valid regular expression
            textResults.setText(
                    "You have an error in your regular expression:\n"
                        + ex.getDescription()
                    );
        }
    }

    /**
     * Figure out the regex options to be passed to the Pattern.compile() class
     * factory based on the state of the checkboxes.
     */
    int getRegexOptions()
    {
        final JCheckBox checkCanonEquivalence    = getCheckCanonEquivalence();
        final JCheckBox checkCaseInsensitive     = getCheckCaseInsensitive();
        final JCheckBox checkDotAll             = getCheckDotAll();
        final JCheckBox checkMultiLine             = getCheckMultiLine();


        int Options = 0;

        if( checkCanonEquivalence.isSelected() ) {
            // In Unicode, certain characters can be encoded in more than one
            // way.
            // Many letters with diacritics can be encoded as a single character
            // identifying the letter with the diacritic, and encoded as two
            // characters: the letter by itself followed by the diacritic by
            // itself
            // Though the internal representation is different, when the string
            // is
            // rendered to the screen, the result is exactly the same.
            Options |= Pattern.CANON_EQ;
        }

        if( checkCaseInsensitive.isSelected() ) {
            // Omitting UNICODE_CASE causes only US ASCII characters to be
            // matched case insensitively
            // This is appropriate if you know beforehand that the subject
            // string will only contain
            // US ASCII characters as it speeds up the pattern matching.
            Options |= Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
        }

        if( checkDotAll.isSelected() ) {
            // By default, the dot will not match line break characters.
            // Specify this option to make the dot match all characters,
            // including line breaks
            Options |= Pattern.DOTALL;
        }

        if( checkMultiLine.isSelected() ) {
            // By default, the caret ^, dollar $ as well as \A, \z and \Z
            // only match at the start and the end of the string
            // Specify this option to make ^ and \A also match after line breaks
            // in the string,
            // and make $, \z and \Z match before line breaks in the string
            Options |= Pattern.MULTILINE;
        }

        return Options;
    }

    /** Pattern constructed by btnObject */
    Pattern compiledRegex;

    /** Matcher object that will search the subject string using compiledRegex */
    Matcher regexMatcher;
    JLabel  jLabel8            = new JLabel();
    JButton btnAdvancedReplace = new JButton();

    /**
     * If you will be using a particular regular expression often, you should
     * create a Pattern object to store the regular expression. You can then
     * reuse the regex as often as you want by reusing the Pattern object.
     * <p>
     *
     * To use the regular expression on a string, create a Matcher object by
     * calling compiledRegex.matcher() passing the subject string to it. The
     * Matcher will do the actual searching, replacing or splitting.
     * <p>
     *
     * You can create as many Matcher objects from a single Pattern object as
     * you want, and use the Matchers at the same time. To apply the regex to
     * another subject string, either create a new Matcher using
     * compiledRegex.matcher() or tell the existing Matcher to work on a new
     * string by calling regexMatcher.reset(subjectString).
     */
    @Override
    public void btnObjects_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
        final JTextArea textSubject         = getTextSubject();
        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
//        final JTextArea textReplace         = getTextReplace();

        compiledRegex = null;
        textReplaceResults.setText( "n/a" );

        try {
            // If you do not want to specify any options (this is the case when
            // all checkboxes in this demo are unchecked), you can omit the
            // second parameter for the Pattern.compile() class factory.
            compiledRegex = Pattern.compile(
                    textRegex.getText(),
                    getRegexOptions()
                    );
            // Create the object that will search the subject string
            // using the regular expression.
            regexMatcher = compiledRegex.matcher( textSubject.getText() );
            textResults.setText( "Pattern and Matcher objects created." );
        }
        catch( PatternSyntaxException ex ) {
            // textRegex does not contain a valid regular expression
            textResults.setText(
                    "You have an error in your regular expression:\n"
                            + ex.getDescription()
                            );
        }
        catch( IllegalArgumentException ex ) { // $codepro.audit.disable logExceptions
            // This exception indicates a bug in getRegexOptions
            textResults.setText(
                    "Undefined bit values are set in the regex options"
                    );
        }
    }

    /**
     * Print the results of a search produced by regexMatcher.find() and stored
     * in regexMatcher.
     */
    void printMatch()
    {
//        final JTextArea textReplaceResults     = getTextReplaceResults();
//        final JTextArea textSubject         = getTextSubject();
//        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
//        final JTextArea textReplace         = getTextReplace();

        try {
            textResults.setText(
                    "Index of the first character in the match: "
                    + Integer.toString( regexMatcher.start() )
                    + "\n"
                    );
            textResults.append(
                    "Index of the first character after the match: "
                            + Integer.toString( regexMatcher.end() )
                            + "\n"
                            );
            textResults.append(
                    "Length of the match: "
                    + Integer.toString(
                            regexMatcher.end()
                            - regexMatcher.start()
                            )
                    + "\n"
                    );
            textResults.append( "Matched text: " + regexMatcher.group() + "\n" );

            if( regexMatcher.groupCount() > 0 ) {
                // Capturing parenthesis are numbered 1..groupCount()
                // group number zero is the entire regex match
                for( int i = 1; i <= regexMatcher.groupCount(); i++ ) {
                    String groupLabel ="Group " + Integer.toString( i );
                    if( regexMatcher.start( i ) < 0 ) {
                        textResults
                                .append( groupLabel
                                        + " did not participate in the overall match\n" );
                    } else {
                        textResults.append( groupLabel + " start: "
                                + Integer.toString( regexMatcher.start( i ) )
                                + "\n" );
                        textResults.append( groupLabel + " end: "
                                + Integer.toString( regexMatcher.end( i ) )
                                + "\n" );
                        textResults.append( groupLabel
                                + " length: "
                                + Integer.toString( regexMatcher.end( i )
                                        - regexMatcher.start( i ) ) + "\n" );
                        textResults.append( groupLabel + " matched text: "
                                + regexMatcher.group( i ) + "\n" );
                    }
                }
            }
        }
        catch( IllegalStateException ex ) { // $codepro.audit.disable logExceptions
            // Querying the results of a Matcher object before calling find()
            // or after a call to find() returned False, throws an
            // IllegalStateException
            // This indicates a bug in our application
            textResults.setText( "Cannot print match results if there aren't any" );
        }
        catch( IndexOutOfBoundsException ex ) { // $codepro.audit.disable logExceptions
            // Querying the results of groups (capturing parenthesis or
            // backreferences)
            // that do not exist throws an IndexOutOfBoundsException
            // This indicates a bug in our application
            textResults.setText( "Cannot print match results of non-existent groups" );
        }
    }

    /**
     * Finds the first match if this is the first search, or if the previous
     * search came up empty. Otherwise, it finds the next match after the
     * previous match.
     * <p>
     *
     * Note that even if you typed in new text for the regex or subject,
     * btnNextMatch uses the subject and regex as they were when you clicked
     * btnCreateObjects.
     */
    @Override
    public void btnNextMatch_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
//        final JTextArea textSubject         = getTextSubject();
//        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
//        final JTextArea textReplace         = getTextReplace();

        textReplaceResults.setText( "n/a" );
        if( regexMatcher == null ) {
            textResults
                    .setText( "Please click Create Objects to create the Matcher object" );
        } else {
            // Caling Matcher.find() without any parameters continues the search
            // at Matcher.end()
            // or starts from the beginning of the string if this is the first
            // search using
            // the Matcher or if the previous search did not find any (further)
            // matches.
            if( regexMatcher.find() ) {
                printMatch();
            } else {
                // This also resets the starting position for find() to the
                // start of the subject string
                textResults.setText( "No further matches" );
            }
        }
    }

    /**
     * Perform a regular expression search-and-replace using a Matcher object.
     * This is the recommended way if you often use the same regular expression
     * to do a search-and-replace. You should also reuse the Matcher object by
     * calling Matcher.reset(nextSubjectString) for improved efficiency.
     * <p>
     *
     * You also need to use the Pattern and Matcher objects for the
     * search-and-replace if you want to use the regex options such as
     * "case insensitive" or "dot all".
     * <p>
     *
     * See the notes with btnReplace for the special $-syntax in the replacement
     * text.
     */
    @Override
    public void btnObjReplace_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
//        final JTextArea textSubject         = getTextSubject();
//        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
        final JTextArea textReplace         = getTextReplace();

        if( regexMatcher == null ) {
            textResults
                    .setText( "Please click Create Objects to create the Matcher object" );
        } else {
            try {
                textReplaceResults.setText( regexMatcher
                        .replaceAll( textReplace.getText() ) );
            }
            catch( IllegalArgumentException ex ) {
                // textReplace contains inapropriate dollar signs
                textResults
                        .setText( "You have an error in the replacement text:\n"
                                + ex.getMessage() );
                textReplaceResults.setText( "n/a" );
            }
            catch( IndexOutOfBoundsException ex ) {
                // textReplace contains a backreference that does not exist
                // (e.g. $4 if there are only three groups)
                textResults
                        .setText( "You have used a non-existent group in the replacement text:\n"
                                + ex.getMessage() );
                textReplaceResults.setText( "n/a" );
            }
        }
    }

    /**
     * Using Matcher.appendReplacement() and Matcher.appendTail() you can
     * implement a search-and-replace of arbitrary complexity. These routines
     * allow you to compute the replacement string in your own code. So the
     * replacement text can be whatever you want.
     * <p>
     *
     * To do this, simply call Matcher.find() in a loop. For each match returned
     * by find(), call appendReplacement() with whatever replacement text you
     * want. When find() can no longer find matches, call appendTail().
     * <p>
     *
     * appendReplacement() appends the substring between the end of the previous
     * match that was replaced with appendReplacement() and the current match.
     * If this is the first call to appendReplacement() since creating the
     * Matcher or calling reset(), then the appended substring starts at the
     * start of the string. Then, the specified replacement text is appended. If
     * the replacement text contains dollar signs, they will be interpreted as
     * usual. E.g. $1 is replaced with the match between the first pair of
     * capturing parentheses.
     * <p>
     *
     * appendTail() appends the substring between the end of the previous match
     * that was replaceced with appendReplacement() and the end of the string.
     * If appendReplacement() was not called since creating the Matcher or
     * calling reset(), the entire subject string is appended.
     * <p>
     *
     * The above means that you should call Matcher.reset() before starting the
     * operation, unless you're sure the Matcher is freshly constructed. If
     * certain matches do not need to be replaced, simply skip calling
     * appendReplacement() for those matches. (Calling appendReplacement() with
     * Matcher.group() as the replacement text will only hurt performance and
     * may get you into trouble with dollar signs that may appear in the regex
     * match.)
     */
    @Override
    public void btnAdvancedReplace_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
//        final JTextArea textSubject         = getTextSubject();
//        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
//        final JTextArea textReplace         = getTextReplace();

        if( regexMatcher == null ) {
            textResults
                    .setText( "Please click Create Objects to create the Matcher object" );
        } else {
            // We will store the replacement text here
            StringBuffer replaceResult = new StringBuffer();
            while( regexMatcher.find() ) {
                try {
                    // In this example, we simply replace the regex match with
                    // the same text in uppercase.
                    // Note that appendReplacement parses the replacement text
                    // to substitute $1, $2, etc.
                    // with the contents of the corresponding capturing
                    // parenthesis just like replaceAll()
                    regexMatcher.appendReplacement( replaceResult, regexMatcher
                            .group().toUpperCase() ); // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.internationalization.useLocaleSpecificMethods
                }
                catch( IllegalStateException ex ) { // $codepro.audit.disable logExceptions
                    // appendReplacement() was called without a preceding
                    // successful call to find()
                    // This exception indicates a bug in your source code
                    textResults.setText( "appendReplacement() called without a prior successful call to find()" );
                    textReplaceResults.setText( "n/a" );
                    return;
                }
                catch( IllegalArgumentException ex ) {
                    // Replacement text contains inapropriate dollar signs
                    textResults.setText( "Error in the replacement text:\n"
                            + ex.getMessage() );
                    textReplaceResults.setText( "n/a" );
                    return;
                }
                catch( IndexOutOfBoundsException ex ) {
                    // Replacement text contains a backreference that does not
                    // exist
                    // (e.g. $4 if there are only three groups)
                    textResults
                            .setText( "Non-existent group in the replacement text:\n"
                                    + ex.getMessage() );
                    textReplaceResults.setText( "n/a" );
                    return;
                }
            }
            regexMatcher.appendTail( replaceResult );
            textReplaceResults.setText( replaceResult.toString() );
            textResults.setText( "n/a" );
            // After using appendReplacement and appendTail, the Matcher object
            // must be reset
            // so we can use appendReplacement and appendTail again.
            // In practice, you will probably put this call at the start of the
            // routine
            // where you want to use appendReplacement and appendTail.
            // I did not do that here because this way you can click on the Next
            // Match button
            // a couple of times to skip a few matches, and then click on the
            // Advanced Replace button to observe that appendReplace() will copy
            // the skipped
            // matches unchanged.
            regexMatcher.reset();
        }
    }

    /**
     * If you want to split many strings using the same regular expression, you
     * should create a Pattern object and call Pattern.split() rather than
     * String.split(). Both methods produce exactly the same results. However,
     * when creating a Pattern object, you can specify options such as
     * "case insensitive" and "dot all".
     * <p>
     *
     * Note that no Matcher object is used.
     */
    @Override
    public void btnObjSplit_actionPerformed( ActionEvent e )
    {
        final JTextArea textReplaceResults     = getTextReplaceResults();
        final JTextArea textSubject         = getTextSubject();
//        final JTextArea textRegex             = getTextRegExp();
        final JTextArea textResults         = getTextResults();
//        final JTextArea textReplace         = getTextReplace();

        textReplaceResults.setText( "n/a" );
        if( compiledRegex == null ) {
            textResults
                    .setText( "Please click Create Objects to compile the regular expression" );
        } else {
            printSplitArray( compiledRegex
                    .split( textSubject.getText() /* , Limit */) );
        }
    }
    }
    @Override // HyperlinkListener
    public void hyperlinkUpdate( HyperlinkEvent hle )
    {
        if( HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType()) ) {
            URL url = hle.getURL();

            try {
                DesktopHelper.browse( url );
                }
            catch( PlatformDesktopNotSupportedException e ) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                }
            }
    }
}
